package com.sky.executor;

import com.sky.config.BoundSql;
import com.sky.pojo.Configuration;
import com.sky.pojo.MappedStatement;
import com.sky.utils.GenericTokenParser;
import com.sky.utils.ParameterMapping;
import com.sky.utils.ParameterMappingTokenHandler;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description sql执行器
 * @Author gaotianzhi
 * @Date 2023-10-31 16:46
 */
public class SimpleExecutor implements Executor {

    @Override
    public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object parameter) throws Exception {
        Connection connection = configuration.getDataSource().getConnection();

        //转换占位符
        String sql = mappedStatement.getSql();
        BoundSql boundSql = getBoundSQL(sql);
        String finalSql = boundSql.getFinalSql();
        PreparedStatement preparedStatement = connection.prepareStatement(finalSql);

        String parameterType = mappedStatement.getParameterType();
        Class<?> parameterTypeClass = Class.forName(parameterType);

        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        for (int i = 0; i < parameterMappings.size(); i++) {
            String filedName = parameterMappings.get(i).getContent();
            Field declaredField = parameterTypeClass.getDeclaredField(filedName);
            declaredField.setAccessible(true);
            Object filedValue = declaredField.get(parameter);
            preparedStatement.setObject(i + 1, filedValue);
        }

        ResultSet resultSet = preparedStatement.executeQuery();
        String resultType = mappedStatement.getResultType();
        Class<?> resultTypeClass = Class.forName(resultType);
        ResultSetMetaData metaData = resultSet.getMetaData();

        List<E> list = new ArrayList();
        while (resultSet.next()) {
            Object o = resultTypeClass.getConstructor().newInstance();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                String columnName = metaData.getColumnName(i);
                Object columnValue = resultSet.getObject(columnName);

                Field declaredField = resultTypeClass.getDeclaredField(columnName);
                declaredField.setAccessible(true);
                declaredField.set(o, columnValue);
            }
            list.add((E) o);
        }

        return list;
    }

    private BoundSql getBoundSQL(String sql) {
        // 标记处理器：配合标记解析器完成标记的解析工作
        ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        // 标记解析器
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
        // 获取到了将#{}替换成？的sql
        String finalSql = genericTokenParser.parse(sql);
        List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();
        return new BoundSql(finalSql, parameterMappings);
    }

}
